package com.emeraldparser.util;

import com.google.common.base.Objects;

public abstract class AbstractGraphEdge<V, E> implements Graph.Edge<V, E> {

	private final V source;
	private final V destination;
	private final E label;

	public AbstractGraphEdge(V source, V destination, E label) {
		this.source = source;
		this.destination = destination;
		this.label = label;
	}

	@Override
	public boolean comesFrom(V vertex) {
		if (isDirected()) {
			return Objects.equal(source, vertex);
		} else {
			return touches(vertex);
		}
	}

	@Override
	public boolean goesTo(V vertex) {
		if (isDirected()) {
			return Objects.equal(destination, vertex);
		} else {
			return touches(vertex);
		}
	}

	@Override
	public boolean isBetween(V source, V destination) {
		if (isDirected()) {
			return comesFrom(source) && goesTo(destination);
		} else {
			return (comesFrom(source) && goesTo(destination)) || (comesFrom(destination) && goesTo(source));
		}
	}

	@Override
	public V getSource() {
		return source;
	}

	@Override
	public V getDestination() {
		return destination;
	}

	@Override
	public E getLabel() {
		return label;
	}

	@Override
	public V opposite(V vertex) {
		return Objects.equal(getSource(), vertex) ? getDestination() : getSource();
	}

	@Override
	public boolean touches(V vertex) {
		return Objects.equal(getSource(), vertex)
		    || Objects.equal(getDestination(), vertex);
	}

}
